unit Map_Compare;

interface

uses
  Classes, SysUtils, Class_P2, Class_P1;

type
  TMap_Compare = class(TObject)
  public
    FP21StrsList: TStringList;
    FP22StrsList: TStringList;
    FP11StrsList: TStringList;
    FP12StrsList: TStringList;

    FNewP21StrsList: TStringList;
    FNewP22StrsList: TStringList;
    FNewP11StrsList: TStringList;
    FNewP12StrsList: TStringList;
  private
    procedure _Compare;
    procedure _Compare1;
    procedure _Compare2;
    procedure _Compare12;
    function _CompareP2Index(P2A, P2B: TP2): Integer;
    function _CompareP2(P2A, P2B: TP2): Boolean;
    function _CompareP1(P2A, P2B: TP2): Boolean; overload;
    function _CompareP1(P1A, P1B: TP1): Boolean; overload;
    function _CompareInteger(A, B: Integer): Integer;
    function _CompareLb(A, B: string): Integer;
  public 
    function CreateNullP2: TP2;
    function CreateNullP1: TP1;
    procedure Compare;
    procedure FillP1StrsList;

    class function FindP1FromList(P2A: TP2; P1StrsListA: TStringList): TStringList;
  end;

implementation

uses
  UtilLib;

{ TMap_Compare }

procedure TMap_Compare.Compare;
begin
  if IsEmpty(FP21StrsList) and IsEmpty(FP22StrsList) then
  begin
    _Compare;
    Exit;
  end;
  if not IsEmpty(FP21StrsList) and IsEmpty(FP22StrsList) then
  begin
    _Compare1;
    Exit;
  end;
  if IsEmpty(FP21StrsList) and not IsEmpty(FP22StrsList) then
  begin
    _Compare2;
    Exit;
  end;
  if not IsEmpty(FP21StrsList) and not IsEmpty(FP22StrsList) then
  begin
    _Compare12;
    Exit;
  end;
end;

procedure TMap_Compare.FillP1StrsList;
var
  Index1, Index2, N, I: Integer;
  P1A, P1B: TP1;
begin
  FNewP11StrsList := TStringList.Create;
  FNewP12StrsList := TStringList.Create;
  Index1 := 0;
  Index2 := 0;
  while (Index1 < FP11StrsList.Count) and (Index2 < FP12StrsList.Count) do
  begin
    P1A := TP1(FP11StrsList.Objects[Index1]);
    P1B := TP1(FP12StrsList.Objects[Index2]);
    N := _CompareInteger(P1A.BH, P1B.BH);
    if N = 0 then
    begin
      FNewP11StrsList.AddObject('', P1A.CopyIt);
      FNewP12StrsList.AddObject('', P1B.CopyIt);
      Index1 := Index1 + 1;
      Index2 := Index2 + 1;
    end else if N = -1 then
    begin
      FNewP11StrsList.AddObject('', P1A.CopyIt);
      FNewP12StrsList.AddObject('', CreateNullP1);
      Index1 := Index1 + 1;
    end else
    begin
      FNewP11StrsList.AddObject('', CreateNullP1);
      FNewP12StrsList.AddObject('', P1B.CopyIt);
      Index2 := Index2 + 1;
    end;
  end;
  if (Index1 = FP11StrsList.Count) and (Index2 < FP12StrsList.Count) then
  begin
    for I := Index2 to FP12StrsList.Count - 1 do
    begin
      P1B := TP1(FP12StrsList.Objects[I]);
      FNewP11StrsList.AddObject('', CreateNullP1);
      FNewP12StrsList.AddObject('', P1B.CopyIt);
    end;
  end; 
  if (Index1 < FP11StrsList.Count) and (Index2 = FP12StrsList.Count) then
  begin
    for I := Index1 to FP11StrsList.Count - 1 do
    begin
      P1A := TP1(FP11StrsList.Objects[I]);
      FNewP11StrsList.AddObject('', P1A.CopyIt);
      FNewP12StrsList.AddObject('', CreateNullP1);
    end;
  end;

  FreeAndNil(FP11StrsList);
  FreeAndNil(FP12StrsList);
end;

class function TMap_Compare.FindP1FromList(P2A: TP2;
  P1StrsListA: TStringList): TStringList;
var
  I: Integer;
  P1A: TP1;
begin
  Result := TStringList.Create;
  if P2A.YUE = 0 then Exit;
  if IsEmpty(P1StrsListA) then Exit;
  for I := 0 to P1StrsListA.Count - 1 do
  begin
    P1A := TP1(P1StrsListA.Objects[I]);
    if (P1A.YUE = P2A.YUE) and (P1A.LB = P2A.LB) and (P1A.PDH = P2A.PDH) then
    begin
      Result.AddObject('', P1A);
    end;
  end;
end;

procedure TMap_Compare._Compare;
begin
  FNewP21StrsList := TStringList.Create;
  FNewP11StrsList := TStringList.Create;
  FNewP22StrsList := TStringList.Create;
  FNewP12StrsList := TStringList.Create;

  FreeListAndNil(FP21StrsList);
  FreeListAndNil(FP11StrsList);
  FreeListAndNil(FP22StrsList);
  FreeListAndNil(FP12StrsList);
end;

procedure TMap_Compare._Compare1;
var
  I: Integer;
begin
  FNewP21StrsList := FP21StrsList;
  FNewP11StrsList := FP11StrsList;
  FNewP22StrsList := TStringList.Create;
  FNewP12StrsList := TStringList.Create;
  for I := 0 to FP21StrsList.Count - 1 do
  begin
    FNewP22StrsList.AddObject('', CreateNullP2);
  end;

  FP21StrsList := nil;
  FP11StrsList := nil;
  FreeListAndNil(FP22StrsList);
  FreeListAndNil(FP12StrsList);
end;

procedure TMap_Compare._Compare12;
var
  P2A, P2B: TP2;
  IndexA, IndexB, N, I: Integer;
begin
  FNewP21StrsList := TStringList.Create;
  FNewP11StrsList := FP11StrsList;
  FNewP22StrsList := TStringList.Create;
  FNewP12StrsList := FP12StrsList;

  IndexA := 0;
  IndexB := 0;
  while (IndexA < FP21StrsList.Count) and (IndexB < FP22StrsList.Count) do
  begin
    P2A := TP2(FP21StrsList.Objects[IndexA]);
    P2B := TP2(FP22StrsList.Objects[IndexB]);
    N := _CompareP2Index(P2A, P2B);
    if N = 0 then
    begin
      if not _CompareP2(P2A, P2B) then
      begin
        P2A._State := 1;
        P2B._State := 1;
      end else
      begin
        if not _CompareP1(P2A, P2B) then
        begin
          P2A._State := 1;
          P2B._State := 1;
        end;
      end;
      FNewP21StrsList.AddObject('', P2A);
      FNewP22StrsList.AddObject('', P2B);
      IndexA := IndexA + 1;
      IndexB := IndexB + 1;
    end else if N = -1 then
    begin
      P2A._State := 1;
      FNewP21StrsList.AddObject('', P2A);
      FNewP22StrsList.AddObject('', CreateNullP2);
      IndexA := IndexA + 1;
    end else
    begin
      P2B._State := 1;
      FNewP21StrsList.AddObject('', CreateNullP2);
      FNewP22StrsList.AddObject('', P2B);
      IndexB := IndexB + 1;
    end;
  end;
  if (IndexA = FP21StrsList.Count) and (IndexB < FP22StrsList.Count) then
  begin
    for I := IndexB to FP22StrsList.Count - 1 do
    begin
      P2B := TP2(FP22StrsList.Objects[I]);
      P2B._State := 1;
      FNewP21StrsList.AddObject('', CreateNullP2);
      FNewP22StrsList.AddObject('', P2B);
    end;
  end else if (IndexB = FP22StrsList.Count) and (IndexA < FP21StrsList.Count) then
  begin
    for I := IndexA to FP21StrsList.Count - 1 do
    begin  
      P2A := TP2(FP21StrsList.Objects[I]);
      P2A._State := 1;
      FNewP21StrsList.AddObject('', P2A);
      FNewP22StrsList.AddObject('', CreateNullP2);
    end;
  end;

  FreeAndNil(FP21StrsList);
  FP11StrsList := nil;
  FreeAndNil(FP22StrsList);
  FP12StrsList := nil;
end;

procedure TMap_Compare._Compare2;
var
  I: Integer;
begin
  FNewP21StrsList := TStringList.Create;
  FNewP11StrsList := TStringList.Create;
  FNewP22StrsList := FP22StrsList;
  FNewP12StrsList := FP12StrsList;
  for I := 0 to FP22StrsList.Count - 1 do
  begin
    FNewP21StrsList.AddObject('', CreateNullP2);
  end;
   
  FreeListAndNil(FP21StrsList);
  FreeListAndNil(FP11StrsList);
  FP22StrsList := nil;
  FP12StrsList := nil;
end;

function TMap_Compare._CompareInteger(A, B: Integer): Integer;
begin
  if A = B then
  begin
    Result := 0;
  end else if A < B then
  begin
    Result := -1; 
  end else
  begin
    Result := 1;
  end;
end;

function TMap_Compare._CompareLb(A, B: string): Integer;
begin
  if A = '~' then A := '0';
  if B = '~' then B := '0';
  Result := _CompareInteger(StrToInt(A), StrToInt(B));
end;

function TMap_Compare._CompareP1(P1A, P1B: TP1): Boolean;
begin
  Result := False;
  if P1A.YUE <> P1B.YUE then Exit;
  //if P1A.ZPDH <> P1B.ZPDH then Exit;
  if P1A.LB <> P1B.LB then Exit;
  if P1A.PDH <> P1B.PDH then Exit;
  if P1A.BH <> P1B.BH then Exit;
  if P1A.RI <> P1B.RI then Exit;
  if P1A.ZY <> P1B.ZY then Exit;
  if P1A.KMH <> P1B.KMH then Exit;
  if P1A.WBZL <> P1B.WBZL then Exit;
  if P1A.JD <> P1B.JD then Exit;
  if P1A.JE <> P1B.JE then Exit;
  if P1A.WBJE <> P1B.WBJE then Exit;
  if P1A.SL <> P1B.SL then Exit;
  if P1A.DZH <> P1B.DZH then Exit;
  if P1A.DZBZ <> P1B.DZBZ then Exit;
  if P1A.KHBM <> P1B.KHBM then Exit;
  if P1A.BMBM <> P1B.BMBM then Exit;
  if P1A.ZYBM <> P1B.ZYBM then Exit;
  if P1A.JSFSBM <> P1B.JSFSBM then Exit;
  if P1A.YWBH <> P1B.YWBH then Exit;
  if P1A.FDATE <> P1B.FDATE then Exit;
  if P1A.CASHID <> P1B.CASHID then Exit;
  if P1A.CURMONTH <> P1B.CURMONTH then Exit;
  if P1A.EXCHRATE <> P1B.EXCHRATE then Exit;
  //if P1A.UNITPRICE <> P1B.UNITPRICE then Exit;
  if P1A.PZXZ <> P1B.PZXZ then Exit;
  Result := True;
end;

function TMap_Compare._CompareP1(P2A, P2B: TP2): Boolean;
var
  StrsListA, StrsListB: TStringList;
  P1A, P1B: TP1;
  I: Integer;
begin
  StrsListA := TStringList.Create;
  StrsListB := TStringList.Create;
  for I := 0 to FP11StrsList.Count - 1 do
  begin
    if FP11StrsList[I] = '1' then Continue;
    P1A := TP1(FP11StrsList.Objects[I]);
    if (P1A.YUE = P2A.YUE) and (P1A.Lb = P2A.LB) and (P1A.PDH = P2A.PDH) then
    begin
      FP11StrsList[I] := '1';
      StrsListA.AddObject('', P1A);
    end;
  end;
  for I := 0 to FP12StrsList.Count - 1 do
  begin
    if FP12StrsList[I] = '1' then Continue;
    P1B := TP1(FP12StrsList.Objects[I]);
    if (P1B.YUE = P2B.YUE) and (P1B.Lb = P2B.LB) and (P1B.PDH = P2B.PDH) then
    begin
      FP12StrsList[I] := '1';
      StrsListB.AddObject('', P1B);
    end;
  end;

  if StrsListA.Count <> StrsListB.Count then
  begin
    Result := False;
  end else if StrsListA.Count = 0 then
  begin
    Result := False;
  end else
  begin
    Result := True;
    for I := 0 to StrsListA.Count - 1 do
    begin
      if not _CompareP1(TP1(StrsListA.Objects[I]), TP1(StrsListB.Objects[I])) then
      begin
        Result := False;
        Break;
      end;
    end;
  end;
  FreeAndNil(StrsListA); 
  FreeAndNil(StrsListB);
end;

function TMap_Compare._CompareP2(P2A, P2B: TP2): Boolean;
begin
  Result := False;
  if P2A.YUE <> P2B.YUE then Exit;
  if P2A.LB <> P2B.LB then Exit;
  if P2A.PDH <> P2B.PDH then Exit;
  if P2A.FJZS <> P2B.FJZS then Exit;
  //if P2A.JZR <> P2B.JZR then Exit;
  //if P2A.XGR <> P2B.XGR then Exit;
  //if P2A._SHR <> P2B._SHR then Exit;
  if P2A.FCH <> P2B.FCH then Exit;
  if P2A.PZLY <> P2B.PZLY then Exit;
  if P2A.CURMONTH <> P2B.CURMONTH then Exit;
  //if P2A.MASTER <> P2B.MASTER then Exit;
  //if P2A.DELEGATE <> P2B.DELEGATE then Exit;
  if P2A.CN <> P2B.CN then Exit;
  //if P2A.BOOKBY <> P2B.BOOKBY then Exit;
  //if P2A.IMAGEID <> P2B.IMAGEID then Exit;
  Result := True;
end;

function TMap_Compare._CompareP2Index(P2A, P2B: TP2): Integer;
begin
  Result := _CompareInteger(P2A.YUE, P2B.YUE);
  if Result <> 0 then Exit;
  Result := _CompareLb(P2A.LB, P2B.LB);
  if Result <> 0 then Exit;
  Result := _CompareInteger(P2A.PDH, P2B.PDH);
  if Result <> 0 then Exit;
end;

function TMap_Compare.CreateNullP1: TP1;
begin
  Result := TP1.Create;
  Result.YUE := 0;
end;

function TMap_Compare.CreateNullP2: TP2;
begin
  Result := TP2.Create;
  Result.YUE := 0;
  Result._State := 1;
end;

end.
